/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package grasp1;

import java.util.ArrayList;
import java.util.Random;

/**
 *
 * @author WALTER
 */
public class Grasp {

  //public static float ALPHA = 0.583f;//mas estable un poquito menos
   public static float ALPHA = 0.815f;//menos estable un poquito mayor (mas generalizado)
   public static int ITERACIONES = 10000;
   public static double COSTOOPERACION = 50;
   
  public void ordenarGalletas(ArrayList<Galleta> arregloGalletas){
    Galleta aux = new Galleta();
    for (int i=0; i< arregloGalletas.size() -1 ; i++){
        for(int j=i+1; j< arregloGalletas.size(); j++){
            Galleta a = arregloGalletas.get(i);
            Galleta b = arregloGalletas.get(j);
           if( a.calcularUtilidad() < b.calcularUtilidad()){
               aux = b;
               arregloGalletas.set(j, a);
               arregloGalletas.set(i, aux);
           }
         }
      }
    }
   

   public boolean verificarDemandaCubierta(int[] arr, int numpedido){
       
       for(int i=0; arr[i] < numpedido ;i++){
           return false;
       }
       return true;
       
   }
   
  public void calculaEficiencias(ArrayList<Empleado> aux, TipoGalleta tipo){
      for(int i=0;i < aux.size(); i++){
              for(int j=0; j < tipo.getMaquinasProceso().size();j++){
              int id_tipomaquina = tipo.getMaquinasProceso().get(j);
              int prod = aux.get(i).getProduccion()[id_tipomaquina -1];
              int merm = aux.get(i).getMermas()[id_tipomaquina -1];
              double porc= tipo.getPorcentajesValor().get(j);
              double e = prod*tipo.getPrecio()*porc - merm*tipo.getCosto()*porc;
              aux.get(i).getEficiencia()[id_tipomaquina-1] =e;
             
              }      
      }
  }
   
   public Empleado obtenerSeleccionadoRCL(ArrayList<Empleado> aux, int id_tipomaquina, float alpha){
       
       //ACA ORDENAREMOS LA LISTA SEGUN EL TIPO DE MAQINA 
       
     Empleado empaux = new Empleado();
       
      for (int i=0; i< aux.size() -1 ; i++){//ordenamos la lista del mejor al peor
        for(int j=i+1; j< aux.size(); j++){
            Empleado a = aux.get(i);
            Empleado b = aux.get(j);
           if( a.getEficiencia()[id_tipomaquina-1] < b.getEficiencia()[id_tipomaquina-1]){
               empaux = b;
               aux.set(j, a);
               aux.set(i, empaux);
           }
        }
      }
        
       Empleado mejor = aux.get(0);
       double beta = mejor.getEficiencia()[id_tipomaquina-1];
       Empleado peor = aux.get(aux.size() - 1);
       double tao = peor.getEficiencia()[id_tipomaquina-1];
       int i;
   
       for( i=0;i< aux.size();i++){//calculamos el rango RCL
           
           if(aux.get(i).getEficiencia()[id_tipomaquina-1] >= beta - alpha*(beta - tao) && aux.get(i).getEficiencia()[id_tipomaquina-1]<= beta );//lleno a lista con los candidatos que entran en el rango
           else break;
       }
       Random random = new Random();
       
       return   aux.remove(random.nextInt(i));
           
   }
   public ArrayList<Galleta> copiargall(ArrayList<Galleta> array){
       ArrayList<Galleta> arr = new ArrayList() ;
       for(int i =0;i<array.size();i++){
           Galleta b = array.get(i);
        Galleta a = new Galleta(b.getIdgalleta(),b.getTipogalleta(),b.getNumGalletasPedidas());
        arr.add(a);
       }
       return arr;
   }
   
   public ArrayList<Empleado> copiaremp(ArrayList<Empleado> array){
       ArrayList<Empleado> arr = new ArrayList() ;
       for(int i =0;i<array.size();i++){
           Empleado b = array.get(i);
        Empleado a = new Empleado(b.getIdempleado(),b.getProduccion(),b.getMermas());
        arr.add(a);
       }
       return arr;
   }
    public Solucion graspConstruccion(ArrayList<Empleado> empleados, ArrayList<Galleta> arregloGalletas,int iteraciones , float alpha){
        
        Solucion sol = new Solucion();
        ArrayList<Empleado> empleadosaux= new ArrayList();
        ArrayList<Galleta> galletaaux = new ArrayList();
        Empleado seleccionado;
        ordenarGalletas(arregloGalletas);
        
        for(int i=0;i<iteraciones;i++){//bucle del grasp
            Solucion solucion = new Solucion(); 
            empleadosaux = copiaremp(empleados);
            galletaaux= copiargall(arregloGalletas);
            int tam = galletaaux.size();
            for(int j=0;j<tam ;j++){//arreglo para las 3 galletas
                
                calculaEficiencias(empleadosaux,galletaaux.get(j).getTipogalleta());
                int tam2 = galletaaux.get(j).getTipogalleta().getMaquinasProceso().size();
                int[] arr_demanda = galletaaux.get(j).getDemanda_maq_cubierta();
//                for(int w=0;w<tam2;w++){
//                    arr_demanda[w]= [w];
//                }       
                //creo un arreglo de tamaño igual a la cantidad de maquinas que requiere una determinada galleta    
                int numpedido = galletaaux.get(j).getNumGalletasPedidas();
                while(!verificarDemandaCubierta(arr_demanda, numpedido) && empleadosaux.size() > 0){//mientras no haya cubierto la demanda en todas las maqinas
                         for(int k=0;k < tam2 ;k++){//por cada tipo de maqina de la galleta j
                            seleccionado = null;
                            if(empleadosaux.size() == 0) break;//verificamos si aun hay empleados  
                            int id_tipomaquina = galletaaux.get(j).getTipogalleta().getMaquinasProceso().get(k);                                                 
                            if(arr_demanda[k] < numpedido) {//asigno para ese tipo de maquina si aun falta cubrir 
                               seleccionado = obtenerSeleccionadoRCL(empleadosaux, id_tipomaquina, alpha);//selecciono el candidato
                               arr_demanda[k] = arr_demanda[k] + seleccionado.getCapacidad()[id_tipomaquina-1];
                               
                            }
                            if(seleccionado!= null){
                               seleccionado.setGalletaAsignada(galletaaux.get(j)); 
                               seleccionado.setTipoMaquinaAsignada(id_tipomaquina);
                               solucion.getAsignados().add(seleccionado);
                               solucion.calcularObjetivo(seleccionado, COSTOOPERACION);    
                            }
                     } 
                }
                 galletaaux.get(j).setDemanda_maq_cubierta(arr_demanda);
                galletaaux.get(j).calcularDemandacubierta(arr_demanda);//por ahora estamos definiendo que la demada cubierta de un tipo de galleta sea la demanda cubierta en la ultima maquina del proceso
            }
            solucion.setGalletas(galletaaux);
            if ( sol.getFuncionObjetivo()==0){ sol = solucion;
                
            }
            else if(sol.getFuncionObjetivo() < solucion.getFuncionObjetivo()){ sol = solucion;}

        }
        
        return sol;
    }

public Solucion grasp_run(ArrayList<Empleado> empleados, ArrayList<Galleta> galletas ){

    return this.graspConstruccion(empleados, galletas, ITERACIONES, ALPHA);
}

}
